查看原文
其他

大杀器Unidbg真正的威力

至尊小仙侠 看雪学苑 2022-07-01


看雪论坛作者ID:至尊小仙侠 


论2021如何处理 arm vmp?


在apk安全如今的时代,一切安全措施已经可以比肩pe级别的防护,加壳,ollvm混淆,vmp
 
似乎各大厂商都在不惜用用户的流畅体验度,来换取更安全的防护力度,也是2021了,谁还没有台晓龙855。CPU性能严重溢出,可能就是这些厂商的想法吧,反正不用白不用,这些算力也不是自己的。
 
但是碰到这么强的加固混淆,逆向人员应该如何是好呢?

有图有真相 Unidbg的杀手锏 CPU指令级别Trace


ps:Unidbg跟010Editor更配哦!


今天就来带大家以自身使用的经验去了解一下Unidbg!
 
上面那张图片呢,用的就是小弟魔改的UnidbgTraceCode出来的文件,通过Trace方法可以快速定位某个函数在指令级别的作用,帮助逆向人员更快的分析出想要的算法。
 
当然Unidbg能做的远远不止这些,本文并不是一篇科普文,所以本文假定读者都是有一定基础的同学。

callFunction:

如果你仔细观摩过Uniidbg源码的话,你会发现所有callJniMethodObject最终都会并入一个叫callFunction的函数。

那么我们在分析So的过程中,发现了一个非JNI函数能不能主动调用呢?答案是必须能。

这种好处的体现在于,逆向人员不必使用Jni函数去分析大量的无用代码,而是能精确的定位一个小的Func的具体作用以及算法逻辑。


通过该函数我们能得到这个小函数在内部到底做了什么操作,并且能Trace出更精确的指令文件。
public final Number[] callFunction(Emulator<?> emulator, String symbolName, Object... args) { Symbol symbol = findSymbolByName(symbolName, false); if (symbol == null) { throw new IllegalStateException("find symbol failed: " + symbolName); } if (symbol.isUndef()) { throw new IllegalStateException(symbolName + " is NOT defined"); } return symbol.call(emulator, args);}

该函数的第一个参数毋庸置疑是当前的模拟器:
emulator = createARMEmulator();

第二个参数可以是导出函数名,或者是指定地址偏移,后面的参数就是个变长的参数列表,由逆向人员分析得到。
 
当然如果你是进行so内部函数调用的话,你大概率会填充一个指针,这里在给大家分享一段自己填充char* 类型的函数源码,别的类型参数同理,不再赘述。
private static void CallVMPFunc(Module module,AndroidEmulator emulator){ try { Symbol malloc = module.findSymbolByName("malloc"); Symbol free = module.findSymbolByName("free"); MemoryBlock block = MemoryAllocBlock.malloc(emulator,malloc,free,0x1000); MemoryBlock namebyte = MemoryAllocBlock.malloc(emulator,malloc,free,0x1000); UnidbgPointer blockpoint = block.getPointer(); UnidbgPointer namepoint = namebyte.getPointer(); String name = "magicillusion"; String data = "hello worid"; namepoint.write(name.getBytes()); blockpoint.write(data.getBytes()); Number[] ret = module.callFunction(emulator,0x13B30+1,namepoint,blockpoint,2); UnidbgPointer ret1 = new UnidbgPointer(emulator,ret[0].intValue(),4); String string = ret1.getString(0); System.out.println("Number => " + (string)); } finally { } }

大杀器内置的HOOK框架

当然Unidbg还内置了多种HOOK框架,今天讲一个分析So比较实用的一款HookZz
// 1. 获取HookZz对象IHookZz hookZz = HookZz.getInstance(emulator); // 加载HookZz,支持inline hook,文档看https://github.com/jmpews/HookZz// 2. enable hookhookZz.enable_arm_arm64_b_branch(); // 测试enable_arm_arm64_b_branch,可有可无index = 0; hookZz.replace(module.findSymbolByName("lrand48"), new ReplaceCallback() { @Override public void postCall(Emulator<?> emulator, HookContext context) { ((EditableArm32RegisterContext)context).setR0(0x12345678); int ptrace_args0 = context.getIntArg(0); System.out.println("lrand48=" + ptrace_args0); } },true); //aesdecode hookhookZz.wrap((module.base)+0x39634+1, new WrapCallback<RegisterContext>() { // inline wrap导出函数 UnidbgPointer addr = null; @Override // 4. 方法执行前 public void preCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) { addr= ctx.getPointerArg(0); UnidbgPointer pointerArg = ctx.getPointerArg(1); UnidbgPointer pointer = pointerArg.getPointer(12); int anInt = pointerArg.getInt(8); byte[] byteArray = pointer.getByteArray(0, anInt); String s =xuzi1(byteArray); System.out.println("aes aesdecode= " + s); } @Override // 5. 方法执行后 public void postCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) { byte[] aaaa = addr.getPointer(0).getPointer(12).getByteArray(0,0x30); String s =xuzi1(aaaa); System.out.println("aes aesdecode1= " + s); } });

同理,此框架也支持导出函数HOOK以及InlineHOOK 有了这个方法,在你分析一些函数的时候,可以充当Log的效果或者强行改变一些函数的返回值让你更容易的分析,比如本例中笔者改变了Lrand48的返回值,让函数每次都强行返回0x12345678,这样在逆向分析的时候能让一些不确定性变成可控性。


 


看雪ID:至尊小仙侠

https://bbs.pediy.com/user-home-873999.htm

*本文由看雪论坛 至尊小仙侠 原创,转载请注明来自看雪社区



官网:https://www.bagevent.com/event/6334937



# 往期推荐

1.羊城杯 re wp

2. CVE-2021-26708 利用四字节释放特定地址,修改内存

3.网刃杯逆向wp

4. 一次针对反fart的加壳apk的脱壳经历

5.CVE-2012-0003 winmm.dll MIDI文件堆溢出漏洞分析及利用

6. 驱动级VT技术EPT实现无痕HOOK保护指定进程----VT EPT原理解析和进阶



公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



球分享

球点赞

球在看



点击“阅读原文”,了解更多!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存